<template>
  <!-- 聊天记录 -->
  <div v-if="boxType=='multi'&&box.enable"
       :style="box.useGlassBack ? 'z-index:'+box.zindex+';transform: translate('+box.x+'px, '+box.y+'px);width:'+box.width+'px;height:'+box.height+'px;opacity:'+box.opacity : 'z-index:'+box.zindex+';transform: translate('+box.x+'px, '+box.y+'px);width:'+box.width+'px;height:'+box.height+'px;background-color:'+box.backgroundColor+';opacity:'+box.opacity+''"
       :class="['chat-body', { 'chat-glass-background': box.useGlassBack }]"
       >
    <div class="chatMian">
      <div class="chat">
        <el-scrollbar
            ref="chatRef"
            style="height: 100%;"
        >
          <div
              class="list"
              style="padding-bottom: 50px;"
              ref="chatListRef"
          >
            <div
                class="item"
                v-for="(item, index) in chatList"
                :key="index"
                :class="item.type == 'ask' ? 'ask' : 'reply'"
                ref="chatItemRef"
            >
              <div class="icon">
                <template v-if="getTheme === 'default'">
                  <el-image
                      style="height: 40px;"
                      fit="contain"
                      v-if="item.type == 'ask' && userHeadVisible"
                      :src="userHead"
                  />
                  <el-image
                      fit="contain"
                      style="height: 40px;"
                      v-if="item.type == 'reply' && headVisible"
                      :src="aiHead"
                  />
                </template>
                <template v-else>
                  <div class="avatar-box">
                    <img
                        v-if="item.type == 'ask' && userHeadVisible"
                        :src="userHead"
                    />
                    <img
                        v-if="item.type == 'reply' && headVisible"
                        :src="aiHead"
                    />
                  </div>
                </template>
              </div>
              <div class="main">
                <div class="head">
                  <div :style="'font-size: '+chatBoxFontSize+'px;'" v-show="false" class="left">
                    <span class="user">{{ item.type == 'ask' ? item.userName : '小薇' }}</span>
                    <span class="time">{{ item.createTime }}</span>
                  </div>
                  <div
                      v-show="false"
                      class="right"
                      v-if="item.type == 'reply'"
                  >
                    <i
                        class="el-icon-document-copy copy"
                        @click.stop="handleCopy(item)"
                    ></i>
                    <!-- <i
                      class="el-icon-top like"
                      @click.stop="handleLike(item)"
                    ></i>
                    <i
                      class="el-icon-bottom delike"
                      @click.stop="handleDelike(item)"
                    ></i> -->
                    <!-- <i
                      class="el-icon-refresh refresh"
                      @click.stop="handleRefresh(item)"
                    ></i> -->
                  </div>
                  <div class="thinkBack" v-if="item.showThink&&useThink">
                    <img style="width:12px;margin-right:5px" src="@/assets/images/thingking.png" alt="">
                    <span v-if="item.thinking" style="font-size: 12px;">正在思考...</span>
                    <span v-else-if="!item.thinking&&item.thinkContent&&item.thinkContent.length>0"
                          style="font-size: 12px;">已深度思考</span>
                    <span v-else style="font-size: 12px;">已完成</span>
                  </div>
                </div>
                <div
                    :style="{
                    'font-size': chatBoxFontSize + 'px',
                    'background-color': item.type == 'ask' ? userBubbleBackColor : aiBubbleBackColor,
                    'color': item.type == 'ask' ? userTextColor : aiTextColor,
                    'padding': '8px 12px',
                    'margin': '4px 0'
                  }"
                    class="text"
                >
                  <span v-if="item.type == 'ask'">{{ item.askText }}</span>
                  <div
                      v-if="item.type == 'reply'"
                      class="typewriter"
                  >
                    <div class="thinkContent" v-if="item.thinkContent&&useThink" v-html="item.thinkContent">

                    </div>
                    <el-divider v-if="item.thinkContent&&useThink"/>
                    <div v-html="item.replayContent">

                    </div>
                  </div>
                </div>
              </div>
            </div>

          </div>

          <!-- <div           v-if="showStopBtn"
                         style="width: 100%;display: flex;justify-content: center;align-items: center;height: 100%;">
            <div class=" unselectable"
                 style="position: absolute;bottom: 0px;height: 40px;color:#409eff;cursor: pointer;border:1px solid #409eff;border-radius: 20px;padding-top: 5px;padding-bottom: 5px;padding-left: 15px;padding-right: 15px;display: flex;justify-content: center;align-items: center;"
                 @click="handleStopReply"
            >
              <el-icon color="#409eff">
                <VideoPause/>
              </el-icon>
              停止回答
            </div>
          </div> -->

          <!--          <el-button style="position: absolute;
                    left: 0;
                    right: 0;
                    top: auto;
                    bottom: 0;
                    margin: auto;
                    width: 15%;" @click="handleStopReply"
                    v-if="showStopBtn"
                    type="primary" plain round><el-icon><VideoPause /></el-icon>停止回答</el-button>-->

        </el-scrollbar>
        <!-- 停止按钮 -->
        <!-- <div v-show="showStopBtn&&stopBtnEnable"
             style="width: 100%;display: flex;justify-content: center;align-items: center;">
          <div @click="handleStopReply" class=""
               style="position: absolute;bottom: 0px;height: 40px;color:#409eff;cursor: pointer;border:1px solid #409eff;border-radius: 20px;padding-top: 5px;padding-bottom: 5px;padding-left: 15px;padding-right: 15px;display: flex;justify-content: center;align-items: center; z-index: 100">
            <el-icon color="#409eff">
              <VideoPause/>
            </el-icon>
            停止回答
          </div>
        </div> -->
        <!-- 添加打断词提示 -->
        <!-- <div v-if="showInterruptTip && voiceInterruptWord&&interruptTipEnalbe"
             style="width: 100%;display: flex;justify-content: center;align-items: center;">
          <div class="unselectable"
               style="position: absolute;bottom: -50px;height: 40px;color:#409eff;border:1px solid #409eff;border-radius: 20px;padding: 5px 15px;display: flex;justify-content: center;align-items: center;white-space: nowrap;">
            <span>你可以说"{{ voiceInterruptWord }}"来打断</span>
          </div>
        </div> -->

      </div>

    </div>
  </div>
  <!-- 打断组件容器 -->
  <div
      v-if="(showStopBtn && stopBtnEnable) || (showInterruptTip && voiceInterruptWord && interruptTipEnalbe)"
      :style="'position:absolute;left:0;right:0;top:0;bottom:0;margin:auto;z-index:'+buttonOptions.zindex+';transform: translate('+buttonOptions.x+'px, '+buttonOptions.y+'px);width:'+buttonOptions.width+'px;height:'+buttonOptions.height+'px'"
      class="center"
  >
    <div class="interrupt-container"
         style="width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 10px;">
      <!-- 停止按钮 -->
      <div @click="handleStopReply" v-if="showStopBtn && stopBtnEnable"
           class="unselectable interrupt-stop-button"
           :style="{
                   height: '45%',
                   width:'30%',
                   color: getTheme === 'scientific' ? '#84E6FB' : '#409eff',
                   border: getTheme === 'scientific' ? '1px solid #84E6FB' : '1px solid #409eff',
                   cursor: 'pointer',
                   borderRadius: '2000px',
                   padding: '5px 15px',
                   display: 'flex',
                   justifyContent: 'center',
                   alignItems: 'center',
                   backgroundColor: getTheme === 'scientific' ? '#000A82' : 'rgba(255, 255, 255, 0.9)',
                   fontSize: (buttonOptions?.fontSize || 14) + 'px',
                   whiteSpace: 'nowrap'
                 }">
        <el-icon :color="getTheme === 'scientific' ? '#84E6FB' : '#409eff'" style="margin-right: 5px;">
          <VideoPause/>
        </el-icon>
        停止回答
      </div>

      <!-- 打断词提示 -->
      <div v-if="showInterruptTip && voiceInterruptWord && interruptTipEnalbe"
           class="unselectable interrupt-tip"
           :style="{
                   height: '45%',
                   width:'60%',
                   color: getTheme === 'scientific' ? '#84E6FB' : '#409eff',
                   border: getTheme === 'scientific' ? '1px solid #84E6FB' : '1px solid #409eff',
                   borderRadius: '2000px',
                   padding: '5px 15px',
                   display: 'flex',
                   justifyContent: 'center',
                   alignItems: 'center',
                   backgroundColor: getTheme === 'scientific' ? '#000A82' : 'rgba(255, 255, 255, 0.9)',
                   fontSize: (buttonOptions.fontSize || 14) + 'px',
                   whiteSpace: 'nowrap'
                 }">
        <span>你可以说"{{ voiceInterruptWord }}"来打断</span>
      </div>
    </div>
  </div>
  <!-- 大屏回答 -->
  <div v-if="boxType=='single'&&box.enable"
       :style="'    border-radius: 30px;transform: translate('+box.x+'px, '+box.y+'px);width:'+box.width+'px;height:'+box.height+'px;'+'background-color:'+box.backgroundColor+';opacity:'+box.opacity"
       class="single-box chat-body">
    <div class="single-box__inner">
      <el-text v-if="chatList.length>0" style="color: #000;">{{ chatList[chatList.length - 1].replayContent }}</el-text>
    </div>
  </div>

  <!-- 常见问题 -->
  <div
      v-if="questions.enable"
      :style="'background-image: none;border: none;transform: translate('+questions.x+'px, '+questions.y+'px);width:'+questions.width+'px;height:'+questions.height+'px'"
      class="chat-body">
    <div style="padding: 0;justify-content: center;" class="chatMian">

      <div class="sub">
        <div class="subFastInput"
             :style="'background-color:'+questions.backgroundColor+';opacity:'+questions.opacity">
          <!-- 按钮横排列 -->
          <div v-if="questions.layoutType === 'button-horizontal' || !questions.layoutType"
               class="questions-layout-button-horizontal">
            <div @click="submitFastAst(button)" :style="'font-size: '+questionFontSize+'px;margin-right:5px;'"
                 class="subFastInputBtn"
                 :key="index" v-for="(button, index) in commonQuestions">
              {{ button }}
            </div>
          </div>
          
          <!-- 按钮竖排列 -->
          <div v-else-if="questions.layoutType === 'button-vertical'"
               class="questions-layout-button-vertical">
            <div @click="submitFastAst(button)" :style="'font-size: '+questionFontSize+'px;margin-bottom:5px;'"
                 class="subFastInputBtn"
                 :key="index" v-for="(button, index) in commonQuestions">
              {{ button }}
            </div>
          </div>
          
          <!-- 文本排列 -->
          <div v-else-if="questions.layoutType === 'text-list'"
               class="questions-layout-text-list">
            <div @click="submitFastAst(button)" :style="'cursor: pointer;font-size: '+questionFontSize+'px;margin-bottom:5px;'"
                 class="question-text-item"
                 :key="index" v-for="(button, index) in commonQuestions">
              · {{ button }}
            </div>
          </div>
          
          <!-- 文本框排列 -->
          <div v-else-if="questions.layoutType === 'text-wrap'"
               class="questions-layout-text-wrap">
            <div @click="submitFastAst(button)" :style="'cursor: pointer;font-size: '+questionFontSize+'px;margin-right:8px;margin-bottom:5px;'"
                 class="question-wrap-item"
                 :key="index" v-for="(button, index) in commonQuestions">
              {{ button }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 输入框 -->
  <!--新修改 2025年6月-->
  <div v-if="input.enable&&platform != 'screen'"
       style="background-image: none;border: none"
       :style="'transform: translate('+input.x+'px, '+input.y+'px);width:'+input.width+'px;height:'+input.height +'px;'+';opacity:'+input.opacity"

       class="chat-body">
    <div
        v-show="(inputMode !== 'hold' && inputMode !== 'hold&&text')"
        class="m-input-box">
      <div v-show="inputMode.includes('&&')" class="m-input-toggle-ico"
            :style="[getTheme === 'default' ? 'border-right: 1px solid #E5E5E5':'border-right: 1px solid #2C7EE2']"
           @click="toggleAudioToText">
        <template v-if="getTheme === 'scientific'">
          <img v-if="isSoundWave" src="@/assets/images/shengbobodong-blue.png" alt="">
          <img v-else src="@/assets/images/shurufa-blue.png" alt="">
        </template>
        <template v-else>
          <img v-if="isSoundWave" src="@/assets/images/shengbobodong.png" alt="">
          <img v-else src="@/assets/images/shurufa.png" alt="">
        </template>

      </div>
      <div class="m-input-box-write">
        <input
            v-show="isShowInput"
            type="text"
            id="inputBox"
            @keydown.enter="inputKeydown"
            :style="'color:'+askTextColor+';font-size:' +input.fontSize+'px;'+'background-color:'+input.backgroundColor"
            ref="askTextRef"
            v-model="askText"
            placeholder="说点什么"
            autocomplete="off"
        />
        <div
            v-show="inputMode === 'auto' || inputMode === 'auto&&text'"
            class="m-input-box-write-voice">
          <template v-if="asrVoiceControl?showVoiceAnim:!isMute">
            <img
                v-if="asrVoiceControl?showVoiceAnim:(!isMute&&volume>0.4)"
                src="@/assets/images/voiceAnim.gif" alt="">
            <img v-else src="@/assets/images/voiceAnimNovoice.png" alt="">
          </template>
          <template v-else>
            <img src="@/assets/images/voiceAnimStop.png" alt=""/>
          </template>
        </div>
      </div>

      <div class="m-input-box-btn">
        <div
            v-show="inputMode === 'text' || inputMode === 'text&&auto' || inputMode ==='text&&hold'"
            id="sendBox"
        >
          <span v-if="askText === ''">
            <template v-if="getTheme === 'scientific'">
              <img src="@/assets/images/send-dis-blue.png" alt=""/>
            </template>
            <template v-else>
              <img src="@/assets/images/send-dis.png" alt=""/>
            </template>
          </span>
          <span v-else @click="submitAsk(false)">
            <template v-if="getTheme === 'scientific'">
              <img src="@/assets/images/send-blue.png" alt=""/>
            </template>
            <template v-else>
              <img src="@/assets/images/send-color.png" alt=""/>
            </template>
          </span>
        </div>
        <div
            id="mikeBox"
            v-show="inputMode === 'auto' || inputMode === 'auto&&text'"
        >
          <span v-if="!isMute" @click="toggleMute">
            <template v-if="getTheme === 'scientific'">
              <img src="@/assets/images/no-mute-blue.png" alt="">
            </template>
            <template v-else>
              <img src="@/assets/images/mike-color.png" alt="">
            </template>
          </span>
          <span v-else @click="toggleMute">
            <template v-if="getTheme === 'scientific'">
              <img src="@/assets/images/mute-blue.png" alt="">
            </template>
            <template v-else>
              <img src="@/assets/images/mike-dis.png" alt="">
            </template>
          </span>
        </div>
      </div>
    </div>

    <div v-show="(inputMode ==='hold' || inputMode === 'hold&&text')" class="m-voice-box">
      <div class="m-voice-animate" v-show="!isMute&&volume>0.4&&btnHolding">
        <img src="@/assets/images/shengbo.gif" alt="">
      </div>
      <button
          @touchstart="holdToSpeak"
          @touchcancel="releaseToStop"
          @touchend="releaseToStop"
          @pointerdown="holdToSpeak"
          @pointerup="releaseToStop"
          @contextmenu.prevent
      >
        <img src="@/assets/images/voice-press.png" alt=""
             @contextmenu.prevent
        >
        <p class="btn-text">
          按住说话
        </p>
      </button>
      <div class="m-voice-animate" v-show="!isMute&&volume>0.4&&btnHolding">
        <img src="@/assets/images/shengbo.gif" alt="">
      </div>

      <div v-show="inputMode === 'text&&hold' || inputMode === 'hold&&text'" class="toggle-keyboard"
           @click="toggleAudioToText"
      >
        <img src="@/assets/images/shurufa.png" alt="">
      </div>
    </div>
  </div>

  <div v-show="!isMute&&btnHolding" class="voice-pop"></div>
  <!-- 放在cornerControl里控制 -->
  <!-- <button v-if="input.enable&&platform !== 'screen'" class="mute-button" @click="handleAgentVoice">
    <img v-if="isMuteIco" src="@/assets/images/laba-on.png" alt="">
    <img v-else src="@/assets/images/laba-off.png" alt="">
  </button> -->
  <!-- <h2 style="position: absolute; bottom: 0; font-size: 30px;">
    <div>
      getInputType 默认值: {{ getInputType }}
    </div>
    <div>
      getAudioType 输入方式: {{ getAudioType }}
    </div>
    <div>
      getInputStatu 是否启用input:{{ getInputStatu }}
    </div>

    <div>
      inputMode 当前值: {{ inputMode }} <br>
    </div>
  </h2> -->
</template>

<script>
import '@/styles/chat.scss';

import {getHtmlPlainText, initDate, isNull} from '@/util/common.js'
// import { chatFun, driveUeApi, asrApi } from '@/api/AiHumanWeb/AiHumanWebApi.js'
import {mittTypes} from '@/util/types';
import {getAudioToText} from "@/api/apiRequst"
// import Recorder from "js-audio-recorder";
//必须引入的核心
// import Recorder from 'recorder-core'

//引入mp3格式支持文件；如果需要多个格式支持，把这些格式的编码引擎js文件放到后面统统引入进来即可
// import 'recorder-core/src/engine/mp3'
// import 'recorder-core/src/engine/mp3-engine'
//录制wav格式的用这一句就行
// import 'recorder-core/src/engine/wav'

//可选的插件支持项，这个是波形可视化插件
// import 'recorder-core/src/extensions/frequency.histogram.view.js'
// import 'recorder-core/src/extensions/lib.fft.js'
import {getAssetsFile} from "@/util/common.js"
import {useSceneStore} from '@/stores/scene';
// import { platform } from 'os';

var _this;
export default {
  name: 'AiHumanWebIndex',
  props: {
    boxType: {
      type: String,
      default: 'Multi'
    },
    platform: {
      type: String,
      default: 'Web3d'
    },
    box: {
      type: Object,
      default: null
    },
    input: {
      type: Object,
      default: null
    },
    questions: {
      type: Object,
      default: null
    },
    commonQuestions: {
      type: Array,
      default: []
    },
  },
  data() {
    return {

      loading: false,
      askText: '',
      askTextColor: '#000',
      chatList: [],
      recorder: null,
      volume: null,
      btnHolding: false,
      showStopBtn: false,
      stopBtnEnable: true,
      showInterruptTip: false,
      interruptTipEnalbe: false,
      buttonOptions: false,
      interruptTipEnalbe: false,
      voiceInterruptWord: null,
      interruptButtonColor: this.getTheme === 'scientific' ? '#252D89' : 'rgba(255, 255, 255, 0.9)',
      wave: null,
      recBlob: null,
      showRecordBtn: null,
      sessionId: '',
      recording: true,
      canRecord: false,
      isCtrlPressed: false, // 用于保存 Ctrl 键是否被按下
      getAssetsFile: getAssetsFile,
      currentItem: null,
      currentLocalItem: null,
      isMute: false,
      showVoiceAnim: false,
      asrVoiceControl: false,
      startMessage: true,
      questionFontSize: 15,
      chatBoxFontSize: 15,
      waitingWordTimeout: null,
      useThink: false,
      headVisible: true, // 数字人头像显示控制
      userHeadVisible: true, // 用户头像显示控制
      userHead: getAssetsFile('head_man.png'),
      aiHead: getAssetsFile('head_ai.png'),
      sceneStore: useSceneStore(),
      isMuteIco: true, // 右上角喇叭
      inputMode: 'text',
      isSoundWave: true, // 输入框图标默认显示声波
      isShowInput: true, // 显示input状态
    };
  },
  computed: {
    // 输入内容 默认值 text 文本： audio语音
    getInputType() {
      const inputType = this.sceneStore.projectConfig.uiConfig.chatbox.input.type;
      return inputType;
    },
    // 是否启用文本输入
    getInputStatu() {
      const textEnable = this.sceneStore.projectConfig.uiConfig.chatbox.input.textEnable;
      return textEnable;
    },
    getAudioType() {
      const audioType = this.sceneStore.projectConfig.uiConfig.chatbox.input.audioType;
      return audioType;
    },
    getTheme() {
      return this.sceneStore.projectConfig.uiConfig.style.type
    },

    // 获取用户消息气泡背景色
    userBubbleBackColor() {
      return (this.box && this.box.userBubbleBackColor) || '#e3f2fd'
    },

    // 获取用户消息文字颜色
    userTextColor() {
      return (this.box && this.box.userTextColor) || '#1976d2'
    },

    // 获取AI回复气泡背景色
    aiBubbleBackColor() {
      return (this.box && this.box.aiBubbleBackColor) || '#f5f5f5'
    },

    // 获取AI回复文字颜色
    aiTextColor() {
      return (this.box && this.box.aiTextColor) || '#333333'
    }
  },
  methods: {
    toggleAudioToText() {
      let inputBox = document.querySelector('#inputBox')
      let autoBox = document.querySelector('.m-input-box-write-voice')
      let sendBox = document.querySelector('#sendBox')
      let mikeBox = document.querySelector('#mikeBox')
      let inputContainer = document.querySelector('.m-input-box')
      let holdBox = document.querySelector('.m-voice-box')

      if (this.inputMode === 'text&&auto' || this.inputMode === 'auto&&text') {
        if (this.isSoundWave) {
          // inputBox.style.display = 'none'
          this.isShowInput = false
          autoBox.style.display = 'flex'
          sendBox.style.display = 'none'
          mikeBox.style.display = 'flex'
          this.isSoundWave = false
          if (this.isMute) {
            this.toggleMute()
          }
        } else {
          // inputBox.style.display = 'block'
          this.isShowInput = true
          autoBox.style.display = 'none'
          sendBox.style.display = 'flex'
          mikeBox.style.display = 'none'
          this.isSoundWave = true
          if (!this.isMute) {
            this.toggleMute()
          }
        }
      }
      if (this.inputMode === 'text&&hold' || this.inputMode === 'hold&&text') {
        if (this.isSoundWave) {
          inputContainer.style.display = 'none'
          this.isShowInput = false
          holdBox.style.display = 'flex'
          this.isSoundWave = false
          if (this.isMute) {
            this.toggleMute()
          }
        } else {
          inputContainer.style.display = 'flex'
          this.isShowInput = true
          // inputBox.style.display = 'block'
          sendBox.style.display = 'flex'
          holdBox.style.display = 'none'
          this.isSoundWave = true
          if (!this.isMute) {
            this.toggleMute()
          }
        }

      }
    },
    toggleMode() {
      if (this.getInputType === 'text' && this.getInputStatu && this.getAudioType === 'none') {
        //   只显示文本输入 不显示其他
        this.inputMode = 'text'
        this.isShowInput = true
        if (!this.isMute) {
          this.toggleMute()
        }
      }
      if (this.getInputType === 'audio' && !this.getInputStatu && this.getAudioType === 'hold') {
        this.inputMode = 'hold'
        this.isShowInput = false
        if (!this.isMute) {
          this.toggleMute()
        }
      }

      if (this.getInputType === 'audio' && !this.getInputStatu && this.getAudioType === 'auto') {
        this.inputMode = 'auto'
        this.isShowInput = false
      }

      if (this.getInputType === 'text' && this.getInputStatu && this.getAudioType === 'auto') {
        this.inputMode = 'text&&auto'
        this.isSoundWave = true
        this.isShowInput = true
        if (!this.isMute) {
          this.toggleMute()
        }
      }
      if (this.getInputType === 'audio' && this.getInputStatu && this.getAudioType === 'auto') {
        this.inputMode = 'auto&&text'
        this.isSoundWave = false
        this.isShowInput = false
      }
      if (this.getInputType === 'audio' && this.getInputStatu && this.getAudioType === 'hold') {
        this.inputMode = 'hold&&text'
        this.isSoundWave = false
        this.isShowInput = false
        if (!this.isMute) {
          this.toggleMute()
        }
      }
      if (this.getInputType === 'text' && this.getInputStatu && this.getAudioType === 'hold') {
        this.inputMode = 'text&&hold'
        this.isSoundWave = true
        this.isShowInput = true
        if (!this.isMute) {
          this.toggleMute()
        }
      }
      //兼容老数据
      if (this.getInputType === 'audioText') {
        this.inputMode = 'text&&auto'
        this.isSoundWave = true
        this.isShowInput = true
        if (!this.isMute) {
          this.toggleMute()
        }
      }
    },
    handleAgentVoice() {
      this.isMuteIco = !this.isMuteIco
      this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE_AGENT, this.isMuteIco)
      if (this.isMuteIco) {
        this.emitter.emit(mittTypes.TIMELINE.UNMUTE_AUDIO)
      } else {
        //静音
        this.emitter.emit(mittTypes.TIMELINE.MUTE_AUDIO)
      }
    },
    // 初始化对话气泡颜色
    initializeBubbleColors() {
      // 确保 box 对象存在
      if (!this.box) {
        return;
      }

      // 设置默认颜色值（如果配置中不存在）
      const defaultColors = {
        userBubbleBackColor: '#e3f2fd',
        userTextColor: '#1976d2',
        aiBubbleBackColor: '#f5f5f5',
        aiTextColor: '#333333'
      };

      // 为不存在的颜色属性设置默认值
      Object.keys(defaultColors).forEach(key => {
        if (this.box[key] === undefined) {
          this.box[key] = defaultColors[key];
        }
      });

      // 如果是科学主题，调整默认颜色
      if (this.getTheme === 'scientific') {
        if (!this.box.userBubbleBackColor || this.box.userBubbleBackColor === defaultColors.userBubbleBackColor) {
          this.box.userBubbleBackColor = '#1a237e';
        }
        if (!this.box.userTextColor || this.box.userTextColor === defaultColors.userTextColor) {
          this.box.userTextColor = '#ffffff';
        }
        if (!this.box.aiBubbleBackColor || this.box.aiBubbleBackColor === defaultColors.aiBubbleBackColor) {
          this.box.aiBubbleBackColor = '#263238';
        }
        if (!this.box.aiTextColor || this.box.aiTextColor === defaultColors.aiTextColor) {
          this.box.aiTextColor = '#ffffff';
        }
      }
    },
    inputKeydown(e) {

      if (e.keyCode == 13) {
        e.cancelBubble = true; //ie阻止冒泡行为
        e.stopPropagation();//Firefox阻止冒泡行为
        e.preventDefault(); //取消事件的默认动作*换行
        //以下处理发送消息代码
        // onSendMsg();
        this.submitAsk()
        // console.log(this.textarea);
      }
    },
    // 添加按住说话的方法
    holdToSpeak(event) {
      event.stopPropagation();
      this.btnHolding = true; // 触发显示动画
      // this.isMute = false;
      this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE_MOBILE, true);
    },

    // 添加松开的方法
    releaseToStop() {
      this.btnHolding = false; // 恢复显示文本
      // this.isMute = true;
      this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE_MOBILE, false);
      // 可以在这里处理录音结束逻辑
    },
    /**
     * 切换静音
     */
    toggleMute() {
      if (!this.isMute) {
        this.isMute = true;
        // 移动端需要长按说话
        this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE, false)

        // this.startRecorder();
      } else {
        // this.stopRecorder();
        this.isMute = false;
        this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE, true)

      }
    },
    handleEnter(event) {
      // if (!event.ctrlKey) {
      //   event.preventDefault();
      //   this.submitAsk();
      // }
      this.submitAsk();
    },
    // handleCtrlEnter(event) {
    //   if (event.ctrlKey) {
    //     this.askText += '\n';
    //   }
    // },
    submitFastAst(text) {
      this.loading = true;
      const createTime = new Date().getTime();
      const askItem = {
        id: createTime + '',
        type: 'ask',
        askText: text,
        createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
        userId: 'u1',
        userName: '我',
        userIcon: '/static/img/userIcon.png',
      };
      this.chatList.push(askItem);
      this.scrollToBottom();
      this.emitter.emit(mittTypes.LIVEKIT.MESSAGE_SEND, text)
      this.addLoadingReplyItem(null, true);
      this.emitter.emit(mittTypes.CHATBOX.UPDATE_USER_ACTIVE)
    },

    submitAsk(isFirst = false) {
      if (!isFirst && !this.askText) return;
      this.sceneStore.currentQuestion = this.askText;
      this.sceneStore.currentQuestionType = 'text'
      if (this.sceneStore.currentFlowNodes.length > 0) {
        this.handleStopReply();
        setTimeout(() => {
          this.submitAskNow(isFirst);
        }, 1000);
      } else {
        this.submitAskNow(isFirst);
      }

      if (this.askText.startsWith('#')) {//进入指令模式
        if (this.askText.includes('sleep')) {//进入睡眠模式
          this.emitter.emit(mittTypes.SLEEPING_CONTROL.SLEEP);

        } else if (this.askText.includes('wakeup')) {//唤醒模式
          this.emitter.emit(mittTypes.SLEEPING_CONTROL.WAKEUP);
          //发送唤醒消息
          // this.emitter.emit(mittTypes.LIVEKIT.WAKEUP_AGENT,true)
        }
        return;
      }

    },
    submitAskNow(isFirst) {

      this.loading = true;
      const createTime = new Date().getTime();
      const askItem = {
        id: createTime + '',
        type: 'ask',
        askText: this.askText,
        createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
        userId: 'u1',
        userName: '我',
        userIcon: '/static/img/userIcon.png',
      };
      if (!isFirst) {
        this.chatList.push(askItem);

        this.scrollToBottom();
      } else {
        this.sessionId = 'aihuman_web_' + new Date().getTime();
      }
      this.emitter.emit(mittTypes.LIVEKIT.MESSAGE_SEND, this.askText)
      this.addLoadingReplyItem(null, true);
      this.emitter.emit(mittTypes.CHATBOX.UPDATE_USER_ACTIVE)
    },
    addLoadingReplyItem(message, think) {
      _this.clearCurrentReply();
      const createTime = new Date().getTime();
      const replyItem = {
        id: createTime,
        type: 'reply',
        loading: true,
        showThink: think ? true : false,
        thinking: think ? true : false,
        replayContent: message ? message : '意图识别中.',
        thinkContent: '',
        createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
      };
      _this.chatList.push(replyItem);
      _this.scrollToBottom();
      _this.handleChatReply();
      _this.currentItem = replyItem;
      _this.showStopBtn = true;
      _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_BUTTON, true)
      // 创建循环的省略号效果
      let dotCount = 1;
      const updateDots = () => {
        if (_this.currentItem && _this.currentItem.loading) {
          const dots = '.'.repeat(dotCount);
          _this.currentItem.replayContent = '意图识别中' + dots;
          dotCount = dotCount >= 3 ? 1 : dotCount + 1;
          _this.dotsTimeout = setTimeout(updateDots, 500);
        }
      };
      _this.dotsTimeout = setTimeout(updateDots, 500);
      _this.waitingWordTimeout = setTimeout(() => {
        if (_this.sceneStore.projectConfig.sleepConfig.waitingParams && _this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode) {
          if (typeof (_this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode) == Object) {
            _this.emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, _this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode)
          } else if (Array.isArray(_this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode) && _this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode.length > 0) {
            let random = Math.floor(Math.random() * _this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode.length);
            _this.emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, _this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode[random])
          }
        }

      }, 5000);
      _this.waitingWordLongTimeout = setTimeout(() => {
        if (_this.sceneStore.projectConfig.roleConfig.errorSpeech && _this.sceneStore.projectConfig.roleConfig.errorSpeech.length > 0) {
          _this.emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, _this.sceneStore.projectConfig.sleepConfig.waitingParams.waitingFlowNode)
          let random = Math.floor(Math.random() * _this.sceneStore.projectConfig.roleConfig.errorSpeech.length);
          _this.emitter.emit(mittTypes.RENDERER.ADD_FLOWNODE, _this.sceneStore.projectConfig.roleConfig.errorSpeech[random])
        }

      }, 10000);
    },
    scrollToBottom() {
      this.$nextTick(() => {
        // this.$refs.chatRef.wrapRef.value.scrollTop = this.$refs.chatRef.wrapRef.value.scrollHeight;
        if (this.$refs.chatListRef) {
          const max = this.$refs.chatListRef.clientHeight
          // console.log('max', max) // 如：当 count = 5 时，max = 总项数 * 每一项的高度 + 外边距 * (总项数 - 1)，即 max = 5 * 50px + 20px * (5 - 1) = 330px
          this.$refs.chatRef.setScrollTop(max)
        }
        // this.$refs.chatRef.scrollMenuRes.wrap.scrollTop=this.$refs.chatRef.scrollMenuRes.wrap.scrollHeight
      })
    },
    handleCopy(item) {
      // console.log('复制');
      this.$Clipboard({
        text: getHtmlPlainText(item.replayContent),
      }).then(() => {
        this.$message.success('复制成功')
      }).catch(() => {
        this.$message.error('复制失败')
      });
    },

    handleLike() {
      // console.log('点赞', item.id);
    },
    handleDelike() {
      // console.log('踩', item.id);
    },
    handleRefresh() {
      // console.log('刷新', item.id);
    },

    startTypewriter() {
      // console.log('startTypewriter');
      const lastRef = this.$refs.chatListRef.lastChild.lastChild.lastChild.lastChild;

      const text = lastRef.innerText;
      // console.log('lastRef', lastRef);
      let index = 0;
      lastRef.innerText = '';

      const typingInterval = setInterval(() => {
        lastRef.innerText += text[index];
        this.scrollToBottom();
        index++;
        if (index === text.length) {
          lastRef.className = "";
          clearInterval(typingInterval);
        }
      }, Math.floor(Math.random() * 40) + 40);
    },

    handleRecorder() {
      if (!this.recording) {
        this.recording = true;
        if (this.platform != 'mobile') {
          this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE_MOBILE, true)
        }

      } else {
        this.recording = false;
        if (this.platform != 'mobile') {
          this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE_MOBILE, false)
        }
      }
    },

    startRecorder() {
      this.recording = true;
      if (!this.recorder) {
        console.error("未打开录音");
        this.$message.error("录音失败");
        this.recording = false;
        return
      }
      this.$message.success("开始录音");
      this.recorder.start()

      // console.log("已开始录音");

      // this.recorder.start().then(() => {
      //   console.log('开始录音');
      //   this.recording = true;
      //   this.$message.success("开始录音");
      // }, (error) => {
      //   // 出错了
      //   console.log(`${error.name} : ${error.message}`);
      //   this.recording = false;
      //   this.$message.error("录音失败");
      // });

    },

    stopRecorder() {
      console.log('停止录音');

      if (!this.recorder || this.recorder.duration === 0) {
        console.error("未打开录音");
        this.$message.error("未采集到声音");
        return
      }
      this.recorder.stop((blob, duration) => {
        //blob就是我们要的录音文件对象，可以上传，或者本地播放
        this.recBlob = blob;
        //简单利用URL生成本地文件地址，此地址只能本地使用，比如赋值给audio.src进行播放，赋值给a.href然后a.click()进行下载（a需提供download="xxx.mp3"属性）
        var localUrl = (window.URL || webkitURL).createObjectURL(blob);
        console.log("录音成功", blob, localUrl, "时长:" + duration + "ms");

        this.uploadRecord(blob);//把blob文件上传到服务器

        // this.recorder.close();//关闭录音，释放录音资源，当然可以不释放，后面可以连续调用start
        // this.recorder=null;
        this.recording = false;
      }, (err) => {
        console.error("结束录音出错：" + err);
        this.recorder.close();//关闭录音，释放录音资源，当然可以不释放，后面可以连续调用start
        this.recorder = null;
      });


      // this.recorder.stop();
      // this.recording = false;

      // if (this.recorder == null || this.recorder.duration === 0) {
      //   this.$message.error("未采集到声音");
      //   return false;
      // }

      // console.log(this.recorder.getPCMBlob());

      // let recordWAVBlob = this.recorder.getWAVBlob();

    },
    uploadRecord(blob) {
      const fileOfBlob = new File([blob], new Date().getTime() + ".wav");

      console.log(fileOfBlob);

      getAudioToText(fileOfBlob).then((res) => {
        console.log(res)
        if (res.status === 200 && !isNull(res.data.asr_msg)) {
          console.log(JSON.parse(res.data.asr_msg).alternatives[0].transcript)

          this.askText = JSON.parse(res.data.asr_msg).alternatives[0].transcript;
          this.submitAsk();

        } else {
          this.askText = '';
        }
      })
    },

    transformToUe(dataParams) {
      console.log('transformToUe', dataParams);
    },

    // async driveUe(dataParams) {

    //   /*女生出场*/
    //   const startData = {
    //     "type": 7,
    //     "data": {
    //       "speech": {
    //         "genType": "2",
    //         "ttsInfo": {
    //           "text": dataParams,
    //           "ssml": "<speak xmlns=\"http://www.w3.org/2001/10/synthesis\" version=\"1.0\" xml:lang=\"zh-CN\"><voice name=\"zh-CN-XiaoxiaoNeural\"  xml:gender=\"male\" xml:lang=\"zh-CN\"><prosody rate=\"1\" volum=\"100\">" + dataParams + "</prosody></voice></speak>"
    //         }
    //       },
    //       "modelActions": [
    //         {
    //           "actionId": "Idle_2",
    //           "startTime": "00:00:01:000",
    //           "endTime": "00:00:00:000",
    //         },
    //         {
    //           "actionId": "F-52",
    //           "startTime": "00:00:03:000",
    //           "endTime": "00:00:00:000",
    //         },
    //         {
    //           "actionId": "F-83",
    //           "startTime": "00:00:10:000",
    //           "endTime": "00:00:00:000",
    //         },
    //         {
    //           "actionId": "F-95",
    //           "startTime": "00:00:18:000",
    //           "endTime": "00:00:00:000",
    //         },
    //         {
    //           "actionId": "F-50",
    //           "startTime": "00:00:24:000",
    //           "endTime": "00:00:00:000",
    //         },
    //         {
    //           "actionId": "Idle_3",
    //           "startTime": "00:00:29:000",
    //           "endTime": "00:00:00:000",
    //         },
    //       ],
    //       "nodeTime": 31
    //     }
    //   }

    //   if (window.AiHumanPMSDK.AiHumanIsReady) {
    //     await driveUeApi(startData).then((res) => {
    //       console.log('res', res);
    //       this.handleChatReply();
    //     });
    //   } else {
    //     this.handleChatReply();
    //   }
    // },
    handleStopReply() {
      _this.clearCurrentReply()
      this.emitter.emit(mittTypes.WEBHUMAN.STOP_VISEME_AUDIO)
      this.emitter.emit(mittTypes.LIVEKIT.INTERRUPT)
      this.emitter.emit(mittTypes.LIVEKIT.STOP_REPLY)
      this.emitter.emit(mittTypes.CHATBOX.UPDATE_USER_ACTIVE, true)
      if (_this.currentItem) {
        _this.currentItem.replayContent += '<span style="color:#bbb">(此条回复已被打断)</span>'
      }
      _this.currentItem = null
      _this.showStopBtn = false
      _this.showInterruptTip = false;
      _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_BUTTON, false)
      _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_TIP, false)
    },
    clearCurrentReply() {
      if (_this.currentItem && _this.currentItem.loading) {
        _this.chatList.forEach((element, index) => {
          if (element.replayContent == '意图识别中...' || element.replayContent == '意图识别中.' || element.replayContent == '意图识别中..') {
            _this.chatList.splice(index, 1)
          }

        });
        _this.currentItem = null
      }

    },

    handleChatReply() {
      this.loading = false;
      this.askText = '';
      this.$nextTick(() => {
        if (_this.$refs.askTextRef) {
          _this.$refs.askTextRef.focus();
        }

        // this.startTypewriter();
      })
    },

    checkRecordingSupport() {
      this.recorder.open(() => {
        console.log("录音已打开");
        this.$message.success("获取麦克风权限成功");
        this.canRecord = true;
        if (this.$refs.recwave) {//创建音频可视化图形绘制对象
          this.wave = Recorder.FrequencyHistogramView({
            elem: this.$refs.recwave
            , height: 30
            , lineCount: 30
            , widthRatio: 0.6
            , position: 0
            , minHeight: 1
            , fallDuration: 400
            , stripeEnable: false
            , mirrorEnable: true
            , linear: [0, "#4ebbfa", 1, "#62e2f6"]
            , fullFreq: false
          });
        }
      }, (msg, isUserNotAllow) => {
        //用户拒绝了录音权限，或者浏览器不支持录音
        console.log((isUserNotAllow ? "UserNotAllow，" : "") + "无法录音:" + msg);
        this.$message.error("获取麦克风权限成功失败");
        this.canRecord = false;
      });
      // Recorder.getPermission().then(() => {
      //   this.$message.success("获取麦克风权限成功");
      //   this.canRecord = true;
      // }, (error) => {
      //   console.log(`${error.name} : ${error.message}`);
      //   this.$message.error("获取麦克风权限成功失败");
      //   this.canRecord = false;
      // });

    },

    handleKeyDown(event) {
      if (event.ctrlKey) {
        this.isCtrlPressed = true;
        if (!this.recording) {
          this.startRecorder();
        }
      }

      if (event.key === 'Enter') {
        this.submitAsk();
      }
    },
    handleKeyUp(event) {
      if (!event.ctrlKey) {
        this.isCtrlPressed = false;
        if (this.recording) {
          this.stopRecorder();
        }
      }
    },
    clearWaitingWordTimeout() {
      if (_this.waitingWordTimeout) {
        clearTimeout(_this.waitingWordTimeout)
        _this.waitingWordTimeout = null;
      }
      if (_this.waitingWordLongTimeout) {
        clearTimeout(_this.waitingWordLongTimeout)
        _this.waitingWordLongTimeout = null;
      }
      if (_this.dotsTimeout) {
        clearTimeout(_this.dotsTimeout)
        _this.dotsTimeout = null;
      }
    }
  },
  mounted() {
    // if(this.x>0){
    //   this.left = x;
    //   this.right = 0;
    // }else if(this.x<0){
    //   this.left = 0;
    //   this.right = x;
    // }else{
    //   this.left = 0;
    //   this.right = 0;
    // }

    // this.projectId = '1739858616928337921';
    // this.submitAsk(true);


    // this.recorder = Recorder({
    // 	type:"wav" //录音格式，可以换成wav等其他格式
    // 	,sampleRate:16000 //录音的采样率，越大细节越丰富越细腻
    // 	,bitRate:16 //录音的比特率，越大音质越好
    // 	,onProcess:(buffers,powerLevel,bufferDuration,bufferSampleRate,newBufferIdx,asyncEnd)=>{
    // 		//录音实时回调，大约1秒调用12次本回调
    // 		//可实时绘制波形，实时上传（发送）数据
    // 		if(this.wave) this.wave.input(buffers[buffers.length-1],powerLevel,bufferSampleRate);
    // 	}
    // });

    // this.checkRecordingSupport();

    // this.recorder.onprogress = (params) => {
    //   // console.log('录音时长(秒)', params.duration);
    //   this.askText = parseFloat(params.duration.toFixed(3)) + '秒';
    //   // console.log('录音大小(字节)', params.fileSize);
    //   // console.log('录音音量百分比(%)', params.vol);
    //   // console.log('当前录音的总数据([DataView, DataView...])', params.data);
    // };

    // 监听 keydown 事件
    // window.addEventListener('keydown', this.handleKeyDown);
    // 监听 keyup 事件
    // window.addEventListener('keyup', this.handleKeyUp);
    _this = this;
    if (_this.sceneStore.projectConfig.uiConfig.chatbox.questions.fontSize) {
      _this.questionFontSize = _this.sceneStore.projectConfig.uiConfig.chatbox.questions.fontSize
    }
    if (_this.sceneStore.projectConfig.uiConfig.chatbox.box.fontSize) {
      _this.chatBoxFontSize = _this.sceneStore.projectConfig.uiConfig.chatbox.box.fontSize
    }
    if (_this.sceneStore.projectConfig.uiConfig.interrupt) {
      _this.stopBtnEnable = _this.sceneStore.projectConfig.uiConfig.interrupt.buttonInterrupt
    }
    if (_this.sceneStore.projectConfig.uiConfig.interrupt) {
      _this.interruptTipEnalbe = _this.sceneStore.projectConfig.uiConfig.interrupt.tip
      _this.buttonOptions = _this.sceneStore.projectConfig.uiConfig.interrupt.buttonOptions
    }
    _this.useThink = _this.sceneStore.projectConfig.uiConfig.chatbox.box.useThink
    if (_this.sceneStore.projectConfig.createRoomParam) {
      if (_this.sceneStore.projectConfig.createRoomParam.llmConfig.MODEL_NAME.indexOf('DeepSeek-R1') > -1) {
        _this.useThink = true;
      }
    }
    // 初始化打断词
    if (_this.sceneStore.projectConfig.uiConfig.interrupt.voiceInterruptWords && _this.sceneStore.projectConfig.uiConfig.interrupt.voiceInterruptWords.length > 0) {
      _this.voiceInterruptWord = _this.sceneStore.projectConfig.uiConfig.interrupt.voiceInterruptWords[0]
    }
    const createTime = new Date().getTime();

    // switch (_this.sceneStore.projectConfig.uiConfig.chatbox.input.type) {
    //   case 'audio':
    //     _this.showRecordBtn = false
    //     _this.recording = true
    //     break;
    //   case 'text':
    //     _this.showRecordBtn = false
    //     _this.recording = false
    //     // _this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE, false)
    //     break;
    //   case 'audioText':
    //     _this.showRecordBtn = true
    //     _this.recording = true
    //     if (_this.platform == 'mobile') {
    //       _this.recording = false
    //       _this.emitter.emit(mittTypes.LIVEKIT.AUDIO_ENABLE, false)
    //     }
    //     break;
    // }

    this.emitter.on(mittTypes.LIVEKIT.ASR_SHOW_VOICEANIM, function (value) {
      _this.asrVoiceControl = true
      _this.showVoiceAnim = value
      
    })
    this.emitter.on(mittTypes.LIVEKIT.AUDIO_ENABLE, function (value) {
      _this.isMute = !value
    })
    this.emitter.on(mittTypes.LIVEKIT.MESSAGE_CHAT_RECIVE, function (data) {
      let messageData = data.messageData;
      let from = data.from;
      switch (from) {
        case mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.BOT:
          if (messageData.message.indexOf('<|STT|>') >= 0) {
            return
          }
          // const replyItem = {
          //   id: messageData.id,
          //   type: 'reply',
          //   replayContent: messageData.message,
          //   createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
          // };
          // _this.chatList.push(replyItem);
          // _this.scrollToBottom();
          // _this.handleChatReply();
          // _this.currentItem = replyItem;
          _this.showStopBtn = true;
          if (_this.currentItem) {
            _this.clearWaitingWordTimeout()
            if (_this.currentItem.loading) {
              _this.currentItem.replayContent = ''
              _this.currentItem.loading = false
            }
            _this.currentItem.thinking = false
            _this.currentItem.replayContent += messageData.message
            _this.currentItem.id = messageData.id
            
            // 添加打断词提示逻辑
            if (_this.currentItem.replayContent.length > 100 && _this.voiceInterruptWord && !_this.showInterruptTip) {
              _this.showInterruptTip = true;
              _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_TIP, true)
              // 5秒后自动隐藏
              setTimeout(() => {
                _this.showInterruptTip = false;
                _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_TIP, false)
              }, 5000);
            }
          }
          _this.scrollToBottom();
          // else if(_this.startMessage){
          //   _this.startMessage = false;
          //   _this.addLoadingReplyItem(messageData.message)
          //   _this.currentItem = null;
          // _this.showStopBtn = false;
          // }
          break;
        case mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL:
          // 用户asr结果
          
          const asrItem = {
            id: messageData.id?messageData.id:createTime + '',
            type: 'ask',
            askText: messageData.message,
            createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
            userId: 'u1',
            userName: '我',
            userIcon: '/static/img/userIcon.png',
          };
          // 查找是否已有相同id的item
          const existingIndex = _this.chatList.findIndex(item => item.id === messageData.id);
          if (existingIndex !== -1) {
            // 如果存在，更新该item
            _this.chatList[existingIndex].askText = asrItem.askText;
          } else {
            // 如果不存在，添加新item
            _this.chatList.push(asrItem);
          }
          _this.scrollToBottom();
          if (!data.wakeOrsleepWord) {
            _this.addLoadingReplyItem(null, true);
          }

          _this.handleChatReply();

          break;
      }

    })
    let timeout
    this.emitter.on(mittTypes.RENDERER.FLOWNODE_LIST_END, function () {
      _this.showStopBtn = false;
      // _this.showInterruptTip = false;
      _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_BUTTON, false)
      // _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_TIP,false)
    })
    this.emitter.on(mittTypes.CHATBOX.ADD_WAITING_MESSAGE, function () {
      _this.addLoadingReplyItem(null, true);
    })
    this.emitter.on(mittTypes.CHATBOX.STOP_REPLY, function () {
      _this.handleStopReply();
    })
    this.emitter.on(mittTypes.CHATBOX.CLEAR_WAITING_TIMEOUT, function () {
      _this.clearWaitingWordTimeout();
    })
    this.emitter.on(mittTypes.CHATBOX.ADD_MESSAGE, function (message) {
      _this.addLoadingReplyItem(null, true);
      if (_this.currentItem) {
        _this.clearWaitingWordTimeout()
        _this.currentItem.replayContent = message
        _this.currentItem.loading = false
        _this.currentItem.thinking = false
        _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_BUTTON, true)
        _this.scrollToBottom();
        
      }
    })
    this.emitter.on(mittTypes.CHATBOX.ADD_THINK_MESSAGE, function (thinkMessage) {
      // _this.addLoadingReplyItem(null,thinkMessage);
      if (_this.currentItem) {
        _this.clearWaitingWordTimeout()
        _this.currentItem.thinkContent = thinkMessage
        // _this.currentItem.loading = false
        _this.currentItem.thinking = true
        _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_BUTTON, true)
        _this.scrollToBottom();
        
      }
    })
    this.emitter.on(mittTypes.LIVEKIT.MESSAGE_CHAT_UPDATE, function (data) {
      let messageData = data.messageData;
      let from = data.from;
      switch (from) {
        case mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.BOT:
          // const replyItem = {
          //   id: createTime + '',
          //   type: 'reply',
          //   replayContent: messageData.message,
          //   createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
          // };
          if (messageData.message.indexOf('<|STT|>') >= 0) {
            return
          }
          if (_this.currentItem && _this.currentItem.id == messageData.id) {
            _this.clearWaitingWordTimeout()
            _this.currentItem.replayContent = messageData.message
            _this.currentItem.loading = false
            _this.currentItem.thinking = false
            _this.showStopBtn = true;
            _this.emitter.emit(mittTypes.RENDERER.SET_SHOW_INTERRUPT_BUTTON, true)
            clearTimeout(timeout)
            // timeout = setTimeout(() => {
            //   _this.showStopBtn = false;
            // }, 2000);
            _this.scrollToBottom();
            
          }


          // _this.chatList.push(replyItem);

          // _this.handleChatReply();
          break;
        case mittTypes.LIVEKIT.MESSAGE_CHAT_FROM_TYPE.LOCAL:
          // 用户asr结果
          _this.emitter.emit(mittTypes.CHATBOX.UPDATE_USER_ACTIVE)
          if (messageData.message.indexOf('<|STT|>') >= 0) {
            return
          }
          const asrItem = {
            id: messageData.id?messageData.id:createTime + '',
            type: 'ask',
            askText: messageData.message,
            createTime: initDate(createTime, 'MM-dd HH:mm:ss'),
            userId: 'u1',
            userName: '我',
            userIcon: '/static/img/userIcon.png',
          };
          // 查找是否已有相同id的item
          const existingIndex = _this.chatList.findIndex(item => item.id === (createTime + ''));
          if (existingIndex !== -1) {
            // 如果存在，更新该item
            _this.chatList[existingIndex].askText += asrItem.askText;
          } else {
            // 如果不存在，添加新item
            _this.chatList.push(asrItem);
          }
          _this.scrollToBottom();
          _this.handleChatReply();
          break;
      }

    })
    // this.handleChatReply();

    if (this.sceneStore.projectConfig.uiConfig.style.type == "scientific") {
      this.userHead = getAssetsFile('style/scientific/head_man.png')
      this.aiHead = getAssetsFile('style/scientific/head_ai.png')
      this.askTextColor = '#ffffff'
    } else {
      this.userHead = getAssetsFile('head_man.png')
      this.aiHead = getAssetsFile('head_ai.png')
      this.askTextColor = '#000000'
    }
    if (_this.sceneStore.projectConfig.uiConfig.chatbox.box.headImg && _this.sceneStore.projectConfig.uiConfig.chatbox.box.headImg != '' && _this.sceneStore.projectConfig.uiConfig.chatbox.box.headImg != 'default') {
      _this.aiHead = _this.origin + _this.sceneStore.projectConfig.uiConfig.chatbox.box.headImg
    }
    if (_this.sceneStore.projectConfig.uiConfig.chatbox.box.userHeadImg && _this.sceneStore.projectConfig.uiConfig.chatbox.box.userHeadImg != '' && _this.sceneStore.projectConfig.uiConfig.chatbox.box.userHeadImg != 'default') {
      _this.userHead = _this.origin + _this.sceneStore.projectConfig.uiConfig.chatbox.box.userHeadImg
    }
    // 初始化头像显示状态
    if (_this.sceneStore.projectConfig.uiConfig.chatbox.box.headVisible !== undefined) {
      _this.headVisible = _this.sceneStore.projectConfig.uiConfig.chatbox.box.headVisible;
    }
    if (_this.sceneStore.projectConfig.uiConfig.chatbox.box.userHeadVisible !== undefined) {
      _this.userHeadVisible = _this.sceneStore.projectConfig.uiConfig.chatbox.box.userHeadVisible;
    }

    // 初始化对话气泡颜色配置（兼容不存在新属性的情况）
    this.initializeBubbleColors();

    this.emitter.on(mittTypes.SLEEPING_CONTROL.ON_SLEEP_START, function () {
      if (_this.$refs.askTextRef) {
        _this.$refs.askTextRef.blur();
      }

    })
    this.emitter.on(mittTypes.CHATBOX.UPDATE_CHATBOX_VOLUME, function (volume) {
      _this.volume = volume

    })
    this.emitter.on(mittTypes.CHATBOX.UPDATE_CHATBOX_VOLUME, function (volume) {
      _this.volume = volume

    })
    this.emitter.on(mittTypes.LOADING.START_SCENE, async function () {
      _this.toggleMode()
    })

  },
  beforeDestroy() {
    // 在组件销毁前移除事件监听器
    window.removeEventListener('keydown', this.handleKeyDown);
    window.removeEventListener('keyup', this.handleKeyUp);
  },

};
</script>
<style lang="scss">
.mute-button {
  position: absolute;
  top: 20px;
  right: 20px;
  background: none;
  border: none;
  outline: none;
  margin: 0;
  padding: 0;

  &:focus {
    outline: none;
  }
}

.voice-pop {
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(120, 164, 253, .8));
  height: 35vh;
  width: 100%;
  position: absolute;
  bottom: 0;
  z-index: 1;
}

.toggle-keyboard {
  position: absolute;
  background: #fff;
  height: 80px;
  width: 80px;
  border-radius: 50%;
  cursor: pointer;
  top: 30%;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.btn-text {
  font-size: 18px;
  color: #fff;
}

.m-voice-animate {
  height: 140px;

  img {
    object-fit: contain;
    height: 100%;
  }
}

.m-voice-box {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  inset: 0;

  button {
    background: none;
    border: none;
    outline: none;
    margin: 0;
    padding: 0;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;

    img {
      user-select: none;
      -webkit-touch-callout: none;
      outline: none;
      -webkit-tap-highlight-color: transparent;
      border: none;
      pointer-events: none; // 禁止响应鼠标事件
      -webkit-user-drag: none; // 禁止拖动
    }

    &:active,
    &:focus,
    &:hover {
      img {
        user-select: none;
        -webkit-touch-callout: none;
        outline: none;
        -webkit-tap-highlight-color: transparent;
        border: none;
      }
    }
  }
}

.m-input-box-write-voice {
  width: 100%;
  display: flex;
  align-items: center;
  height: 100%;

  img {
    width: 100%;
    object-fit: contain;
  }

  //button {
  //  background: none;
  //  border: none;
  //  outline: none;
  //  margin: 0;
  //  padding: 0;
  //  user-select: none;
  //
  //  img {
  //    width: 100%;
  //    object-fit: contain;
  //  }
  //}


}

.m-input-box-btn {
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  height: 100%;
  padding-top: 2px;
  aspect-ratio: 1 / 1;

  div {
    flex:1;
    display: flex;
    align-items: center;
    height: 100%;
    justify-content: center;
    span {

      img {
        height: auto;
        width: 80%;
        // 比例
        aspect-ratio: 1 / 1;
        display: inline-block;
        object-fit: contain;
      }
    }
  }
}

.m-input-box-write {
  flex: 1;
  height: 100%;
  padding: 0 8px;
  margin-left: 10px;

  input {
    background: transparent;
    border: none;
    outline: none;
    color: #999;
    font-size: 14px;
    height: 100%;
    width: 100%;

    &::placeholder {
      color: #B1B1B1;
    }
  }
}

.m-input-toggle-ico {
  // width: 6%;
  //height: 100%;
  cursor: pointer;
  padding: 0 10px 0 6px;
  border-right: 1px solid #E5E5E5;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;

  img {
    object-fit: contain;
    height: auto;
    aspect-ratio: 1 / 1;
    width: 50%;
  }
}

.m-input-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #fff;
  border-radius: 15px;
  height: 100%;
  padding: 8px;
}

.chat-content-box {
  flex: 1;
  height: 100%;

  input {
    background: transparent;
    border: none;
    outline: none;
    color: #999;
    font-size: 14px;
    height: 100%;
    width: 100%;
  }
}

.chat-input-box {
  width: 8%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;

  span {
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  img {
    cursor: pointer;
    height: 80%;
    width: 80%;
    object-fit: contain;
  }
}

.single-box {
  padding: 4px;
  border-radius: 30px;
  background: linear-gradient(to bottom, #C786FF, #4883FF);

  &__inner {
    display: flex;
    background: linear-gradient(-15deg, #CDE2F9 0%, #E5E2FF 100%);
    border-radius: 30px;
    height: 100%;
    width: 100%;
    text-align: center;
    padding: 20px;
  }
}

.chat-body {
  position: absolute;
  //background-image: linear-gradient(to right,  #eeeff5,#cde2f9 );
  top: 0px;
  left: 0px;
  bottom: 0px;
  right: 0;
  margin: auto;
  z-index: 1000;
  border-radius: 5px;
  padding: 5px;
  // box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
  // border: 2px #fff solid;
  .typewriter {
    // &::after {
    //   content: "|";
    //   display: inline-block;
    //   animation: blink-caret 0.5s infinite;
    // }
  }

  .el-textarea {
    display: flex;
    align-items: center;
  }

  .recording {
    color: #ff0000;
  }

  .el-icon-microphone-box {
    height: 120%;
    width: 60px;
    display: flex;
    align-items: center;
    justify-content: center;

    .el-icon-microphone {
      font-size: 32px;
      cursor: pointer;
    }
  }
}

.thinkContent {
  color: #737986;
  padding-left: 5px;
  border-left: 1px solid #C0CADE;
}

.thinkBack {
  border-radius: 5px;
  background-color: #ffffff77;
  padding: 5px;
}
</style>
  